"""
Java桥接模块
提供Python调用Java CLI和响应Java请求的完整接口
"""

import json
import subprocess
import tempfile
import time
import logging
from pathlib import Path
from typing import Dict, Any, Optional, Union
import sys

from .protocol import IntegrationProtocol, IntegrationResponse
from .request_handler import RequestHandler
from .concurrent_manager import get_concurrent_manager
from .config_sync import get_config_sync_manager
from .performance_manager import get_performance_manager

class JavaBridge:
    """Java集成桥接器"""
    
    def __init__(self, java_cli_jar: Optional[str] = None):
        """
        初始化Java桥接器
        
        Args:
            java_cli_jar: Java CLI JAR文件路径，如果为None则自动查找
        """
        self.logger = logging.getLogger(__name__)
        self.java_cli_jar = java_cli_jar or self._find_java_cli_jar()
        self.request_handler = RequestHandler()
        
        # 使用管理器
        self.concurrent_manager = get_concurrent_manager()
        self.config_sync = get_config_sync_manager()
        self.performance_manager = get_performance_manager()
        
        # 使用临时目录管理器
        self.temp_dir = self.concurrent_manager.base_dir
    
    def _find_java_cli_jar(self) -> Optional[str]:
        """自动查找Java CLI JAR文件"""
        possible_paths = [
            "java-cli/target/md2ppt-aspose-cli.jar",
            "../java-cli/target/md2ppt-aspose-cli.jar",
            "target/md2ppt-aspose-cli.jar",
            "./md2ppt-aspose-cli.jar"
        ]
        
        for path in possible_paths:
            jar_path = Path(path)
            if jar_path.exists():
                self.logger.info(f"找到Java CLI JAR: {jar_path.absolute()}")
                return str(jar_path.absolute())
        
        self.logger.warning("未找到Java CLI JAR文件，某些功能可能不可用")
        return None
    
    def is_java_available(self) -> bool:
        """检查Java环境是否可用"""
        try:
            if not self.java_cli_jar or not Path(self.java_cli_jar).exists():
                return False
            
            # 测试Java版本
            result = subprocess.run(['java', '-version'], 
                                  capture_output=True, text=True, timeout=10)
            return result.returncode == 0
        except Exception:
            return False
    
    def check_java_engines(self) -> Dict[str, Any]:
        """检查Java端可用的引擎"""
        if not self.is_java_available():
            return {"available": False, "reason": "Java环境不可用"}
        
        try:
            # 使用--help命令测试CLI是否工作
            result = subprocess.run([
                'java', '-jar', self.java_cli_jar, '--help'
            ], capture_output=True, text=True, timeout=30)
            
            if result.returncode == 0:
                return {
                    "available": True,
                    "java_cli_jar": self.java_cli_jar,
                    "help_output": result.stdout[:500]  # 截取前500字符
                }
            else:
                return {
                    "available": False,
                    "reason": f"Java CLI执行失败: {result.stderr}"
                }
        except Exception as e:
            return {
                "available": False,
                "reason": f"检查异常: {str(e)}"
            }
    
    def generate_with_java(self, config_path: Union[str, Path], output_path: Union[str, Path],
                          quality: str = "NORMAL", verbose: bool = False, 
                          dry_run: bool = False, timeout: int = 300) -> Dict[str, Any]:
        """
        使用Java CLI生成演示文稿
        
        Args:
            config_path: 配置文件路径
            output_path: 输出文件路径
            quality: 质量级别 (LOW, NORMAL, HIGH)
            verbose: 详细输出
            dry_run: 试运行模式
            timeout: 超时时间（秒）
        """
        if not self.is_java_available():
            return {
                "success": False,
                "message": "Java环境不可用",
                "java_available": False
            }
        
        config_path = Path(config_path)
        output_path = Path(output_path)
        
        if not config_path.exists():
            return {
                "success": False,
                "message": f"配置文件不存在: {config_path}"
            }
        
        # 生成请求ID并开始性能跟踪
        request_id = self.concurrent_manager.generate_safe_request_id()
        metrics = self.performance_manager.start_request_tracking(request_id)
        
        try:
            # 验证输入参数安全性
            if not self._validate_command_params(config_path, output_path, quality, timeout):
                return {
                    "success": False,
                    "message": "命令参数验证失败",
                    "security_error": True
                }
            
            # 构建命令（使用安全的参数传递）
            cmd = [
                'java', '-jar', str(Path(self.java_cli_jar).resolve()),
                str(Path(config_path).resolve()),
                '-o', str(Path(output_path).resolve()),
                '-q', self._sanitize_quality(quality),
                '-t', str(int(timeout))
            ]
            
            if verbose:
                cmd.append('--verbose')
            if dry_run:
                cmd.append('--dry-run')
            
            # 过滤敏感信息的日志
            safe_cmd = self._sanitize_command_for_logging(cmd)
            self.logger.info(f"执行Java命令: {' '.join(safe_cmd)}")
            
            # 安全执行命令
            start_time = time.time()
            result = subprocess.run(
                cmd, 
                capture_output=True, 
                text=True, 
                timeout=timeout + 60,
                cwd=Path.cwd(),  # 固定工作目录
                env=self._get_safe_environment()  # 清理环境变量
            )
            processing_time = time.time() - start_time
            
            # 解析结果
            success = result.returncode == 0
            
            # 完成性能跟踪
            self.performance_manager.finish_request_tracking(
                request_id, success, 
                result.stderr if not success else None,
                output_path if success and not dry_run else None
            )
            
            response = {
                "success": success,
                "message": "Java生成成功" if success else f"Java生成失败 (退出码: {result.returncode})",
                "java_available": True,
                "processing_time": processing_time,
                "stdout": result.stdout,
                "stderr": result.stderr,
                "exit_code": result.returncode,
                "request_id": request_id
            }
            
            # 如果成功且不是试运行，检查输出文件
            if success and not dry_run and output_path.exists():
                response["output_file"] = {
                    "path": str(output_path.absolute()),
                    "size": output_path.stat().st_size,
                    "exists": True
                }
            
            return response
            
        except subprocess.TimeoutExpired:
            return {
                "success": False,
                "message": f"Java执行超时 ({timeout}秒)",
                "java_available": True,
                "timeout": True
            }
        except Exception as e:
            self.logger.error(f"Java执行异常: {e}", exc_info=True)
            return {
                "success": False,
                "message": f"Java执行异常: {str(e)}",
                "java_available": True,
                "exception": str(e)
            }
    
    def enhance_animations(self, pptx_path: Union[str, Path], 
                          animation_config: Dict[str, Any]) -> Dict[str, Any]:
        """
        使用Java增强动画效果
        
        Args:
            pptx_path: 现有PPTX文件路径
            animation_config: 动画配置
        """
        # 首先将动画配置转换为JSON配置文件
        temp_config = self._create_animation_config(pptx_path, animation_config)
        
        # 创建增强后的输出路径
        pptx_path = Path(pptx_path)
        enhanced_path = pptx_path.parent / f"{pptx_path.stem}_enhanced{pptx_path.suffix}"
        
        # 使用Java CLI进行动画增强
        return self.generate_with_java(
            config_path=temp_config,
            output_path=enhanced_path,
            quality="HIGH",
            verbose=True
        )
    
    def _create_animation_config(self, pptx_path: Path, animation_config: Dict[str, Any]) -> Path:
        """创建动画配置文件"""
        config = {
            "metadata": {
                "title": f"增强动画 - {Path(pptx_path).stem}",
                "author": "MD2PPT Python-Java集成",
                "version": "1.0.0",
                "created": time.strftime("%Y-%m-%d")
            },
            "settings": {
                "theme": "default",
                "quality": "HIGH",
                "timeout_seconds": 300,
                "animation_engine": "ASPOSE_JAVA",
                "fallback_engine": "PYTHON_PPTX"
            },
            "slides": animation_config.get('slides', [])
        }
        
        temp_config = self.temp_dir / f"animation_config_{int(time.time())}.json"
        with open(temp_config, 'w', encoding='utf-8') as f:
            json.dump(config, f, ensure_ascii=False, indent=2)
        
        return temp_config
    
    def _validate_command_params(self, config_path: Union[str, Path], 
                               output_path: Union[str, Path], 
                               quality: str, timeout: int) -> bool:
        """验证命令参数安全性"""
        try:
            # 验证路径安全性
            config_path = Path(config_path).resolve()
            output_path = Path(output_path).resolve()
            
            # 检查路径遍历攻击
            if '..' in str(config_path) or '..' in str(output_path):
                self.logger.warning("检测到路径遍历攻击尝试")
                return False
            
            # 验证文件扩展名
            if config_path.suffix.lower() not in ['.json']:
                self.logger.warning(f"不安全的配置文件扩展名: {config_path.suffix}")
                return False
                
            if output_path.suffix.lower() not in ['.pptx', '.ppt']:
                self.logger.warning(f"不安全的输出文件扩展名: {output_path.suffix}")
                return False
            
            # 验证质量参数
            if quality.upper() not in ['LOW', 'NORMAL', 'HIGH']:
                self.logger.warning(f"无效的质量参数: {quality}")
                return False
            
            # 验证超时参数
            if not isinstance(timeout, int) or timeout < 1 or timeout > 3600:
                self.logger.warning(f"无效的超时参数: {timeout}")
                return False
            
            return True
            
        except Exception as e:
            self.logger.error(f"参数验证异常: {e}")
            return False
    
    def _sanitize_quality(self, quality: str) -> str:
        """清理质量参数"""
        clean_quality = quality.upper().strip()
        return clean_quality if clean_quality in ['LOW', 'NORMAL', 'HIGH'] else 'NORMAL'
    
    def _sanitize_command_for_logging(self, cmd: list) -> list:
        """清理命令用于日志记录（移除敏感路径）"""
        safe_cmd = []
        for arg in cmd:
            if 'temp' in str(arg).lower() or 'private' in str(arg).lower():
                safe_cmd.append('[FILTERED_PATH]')
            else:
                safe_cmd.append(str(arg))
        return safe_cmd
    
    def _get_safe_environment(self) -> dict:
        """获取安全的环境变量"""
        import os
        safe_env = {
            'PATH': os.environ.get('PATH', ''),
            'JAVA_HOME': os.environ.get('JAVA_HOME', ''),
            'LANG': os.environ.get('LANG', 'en_US.UTF-8'),
            'LC_ALL': 'C'
        }
        return {k: v for k, v in safe_env.items() if v}
    
    def process_java_request(self, request_file: Path, response_file: Path) -> bool:
        """
        处理来自Java的请求
        这个方法由Java端调用的Python脚本使用
        """
        try:
            # 处理请求
            response = self.request_handler.handle_request(request_file)
            
            # 写入响应文件
            with open(response_file, 'w', encoding='utf-8') as f:
                json.dump({
                    "success": response.success,
                    "message": response.message,
                    "data": response.data,
                    "processing_time": response.processing_time,
                    "warnings": response.warnings
                }, f, ensure_ascii=False, indent=2)
            
            return True
            
        except Exception as e:
            self.logger.error(f"处理Java请求失败: {e}", exc_info=True)
            
            # 写入错误响应
            try:
                error_response = {
                    "success": False,
                    "message": f"Python处理失败: {str(e)}",
                    "data": {},
                    "processing_time": 0.0,
                    "warnings": []
                }
                
                with open(response_file, 'w', encoding='utf-8') as f:
                    json.dump(error_response, f, ensure_ascii=False, indent=2)
            except:
                pass
            
            return False

# 命令行接口支持（供Java调用）
def main():
    """命令行入口点，供Java端调用"""
    if len(sys.argv) < 3:
        print("用法: python -m md2ppt.integration.java_bridge <script_name> <request_file>")
        sys.exit(1)
    
    script_name = sys.argv[1]
    request_file = Path(sys.argv[2])
    response_file = request_file.parent / f"{request_file.stem}_response.json"
    
    # 设置日志
    logging.basicConfig(level=logging.INFO)
    
    bridge = JavaBridge()
    
    if script_name in ['preprocess.py', 'generate_base.py']:
        # 处理Java请求
        success = bridge.process_java_request(request_file, response_file)
        sys.exit(0 if success else 1)
    else:
        print(f"不支持的脚本: {script_name}")
        sys.exit(1)

if __name__ == "__main__":
    main()